package com.dcivision.dms.core;

import java.io.File;
import java.io.InputStream;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.struts.upload.FormFile;

import com.dcivision.dms.DmsErrorConstant;
import com.dcivision.dms.DmsOperationConstant;
import com.dcivision.dms.bean.DmsContent;
import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.bean.DmsRelationalWord;
import com.dcivision.dms.bean.DmsRoot;
import com.dcivision.dms.bean.DmsVersion;
import com.dcivision.dms.bean.MtmDocumentRelationship;
import com.dcivision.dms.client.analyzer.DmsDocumentAnalyzer;
import com.dcivision.dms.dao.DmsContentDAObject;
import com.dcivision.dms.dao.DmsDocumentDAObject;
import com.dcivision.dms.dao.DmsRelationalWordDAObject;
import com.dcivision.dms.dao.DmsVersionDAObject;
import com.dcivision.dms.dao.MtmDocumentRelationshipDAObject;
import com.dcivision.dms.dao.MtmDocumentVersionDAObject;
import com.dcivision.dms.web.ListDmsDocumentForm;
import com.dcivision.dms.web.MaintDmsVersionForm;
import com.dcivision.dms.web.MaintDmsWindowsClientForm;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.framework.web.AbstractSearchForm;
import com.dcivision.lucene.FieldNames;
import com.dcivision.lucene.IndexDocument;
import com.dcivision.lucene.IndexKeywordParser;
import com.dcivision.lucene.IndexManager;
import com.dcivision.lucene.Pager;
import com.dcivision.user.bean.UserRecord;
import com.dcivision.user.dao.UserRecordDAObject;

/**
 * <p>Class Name:       DmsWinClientOperartionManager    </p>
 * <p>Description:      The class mainly handle the dmsDocument windows client operation process, like create, delete, etc. </p>
 * @author              jerry zhou
 * @company             DCIVision Limited
 * @creation date       01/07/2005
 * @version             $Revision: 1.9.2.1 $
 */

public class DmsWinClientOperartionManager {  
  public static final String REVISION = "$Revision: 1.9.2.1 $";
  protected Log log = LogFactory.getLog(this.getClass().getName());
  protected DmsDocumentAnalyzer documentAnalyzer = null;
  
  private SessionContainer sessionContainer = null;
  private Connection conn=null;  
  
  public static String CLIENT_TYPE_MSWORD = "MSWORD";
  public static String CLIENT_TYPE_MSOUTLOOK = "MSOUTLOOK";  
  public static String CLIENT_TYPE_NOTES = "NOTES";  

  /**
   *  Constructor - Creates a new instance of DmsWinClientOperartionManager
   */
  public DmsWinClientOperartionManager(SessionContainer sessionContainer, Connection conn) {
    this.sessionContainer = sessionContainer;
    this.conn = conn;
  }
  
  /**
   *  Release - To release the variable in instance of DocumentOperationManager
   */
  public void release () {
    this.sessionContainer = null;
    this.conn = null;
  }

  public DmsDocument createDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
    InputStream inputStream = null;
    DmsDocument newDocument = null;
    FormFile formFile = actionForm.getUploadFile();
    
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    RootOperationManager rootOperationManager = new RootOperationManager(sessionContainer, conn);
    DocumentRetrievalManager documentRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    
    try{
      if (DmsDocument.DOCUMENT_TYPE.equals(actionForm.getDocumentType())) {
        //Create Document      
	    if (formFile !=null) {
	      inputStream = formFile.getInputStream();
	    }
	    DmsDocument dmsDocument = (DmsDocument)actionForm.getFormData();
	    dmsDocument.setItemStatus(DmsVersion.AVAILABLE_STATUS);
	    if (formFile!=null) {
	      dmsDocument.setItemSize(new Integer(formFile.getFileSize()));
	    }else{
	      dmsDocument.setItemSize(new Integer(0));
	    }
	    dmsDocument.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
	    
	    newDocument = docOperationManager.createDocument(dmsDocument, inputStream, true, null);
      }else if (DmsDocument.FOLDER_TYPE.equals(actionForm.getDocumentType())) {
        //Create Folder      
    	if("0".equals(actionForm.getParentID())){
    	  DmsRoot dmsRoot = new DmsRoot();
          dmsRoot.setRootName(actionForm.getDocumentName());
          dmsRoot.setRootType(DmsRoot.PUBLIC_ROOT);
          dmsRoot.setLocID(new Integer(1));
          dmsRoot.setStorageLimit(new Double(0));
          dmsRoot.setOwnerID(sessionContainer.getUserRecordID());
                
          dmsRoot = rootOperationManager.createPublicRoot(dmsRoot);
          
          newDocument = documentRetrievalManager.getDocumentByNameParentID(actionForm.getDocumentName(),new Integer(0));
    	}else{
    	  DmsDocument dmsDocument = (DmsDocument)actionForm.getFormData();
          dmsDocument.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
          dmsDocument.setItemStatus(DmsVersion.AVAILABLE_STATUS);
        
          newDocument = docOperationManager.createFolder(dmsDocument);
    	}
      }
    }catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception e){
      log.error(e.getMessage(), e);
      throw new ApplicationException(e);
    }
    return newDocument;
  }
  
  public DmsDocument updateDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
    DmsDocument newDocument = null;
    
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
	    
    try{
      DmsDocumentDAObject dmsDocumentDAObject = new DmsDocumentDAObject(sessionContainer,conn); 
      DmsDocument oldDocument = (DmsDocument) dmsDocumentDAObject.getObjectByID(TextUtility.parseIntegerObj(actionForm.getID()));
      DmsDocument tepDocument = (DmsDocument)actionForm.getFormData();
      oldDocument.setReferenceNo(tepDocument.getReferenceNo());
      oldDocument.setDescription(tepDocument.getDescription());
      oldDocument.setPriority(tepDocument.getPriority());
      oldDocument.setEffectiveEndDate(tepDocument.getEffectiveEndDate());
      newDocument = docOperationManager.updateDocument(oldDocument);
    }catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception e){
      log.error(e.getMessage(), e);
      throw new ApplicationException(e);
    }
    return newDocument;
  }
  
  public void delDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
	    
  	DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
  	DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
  	MtmDocumentRelationshipDAObject dmsMtmDocumentRelationshipDAO = new MtmDocumentRelationshipDAObject (sessionContainer, conn);
  	
  	List relationshipList=new ArrayList();
  	List indirectRelationDocumentList=new ArrayList();
  	try{
  	  String[] selectedID = TextUtility.splitString(actionForm.getID(),",");
  	  for (int i = 0; i < selectedID.length; i++) {
  	    DmsDocument document = docRetrievalManager.getDocumentByID(TextUtility.parseIntegerObj(selectedID[i]));
  	    if (DmsDocument.FOLDER_TYPE.equals(document.getDocumentType()) || DmsDocument.COMPOUND_DOC_TYPE.equals(document.getDocumentType()) || DmsDocument.PAPER_DOC_TYPE.equals(document.getDocumentType())) {
  	      docOperationManager.deleteFolder(document);
  	    } else {
  	      relationshipList=dmsMtmDocumentRelationshipDAO.getListByRelationIDRelationType(document.getID(),null);
  	      indirectRelationDocumentList=dmsMtmDocumentRelationshipDAO.getListByIDRelationType(document.getID(),null);
  	      if(relationshipList.size()>0){
  	        for(int n=0;n<relationshipList.size();n++){
  	          MtmDocumentRelationship relationshipObj = (MtmDocumentRelationship)relationshipList.get(n);
  	          relationshipObj.setRecordStatus(GlobalConstant.RECORD_STATUS_INACTIVE);
  	          dmsMtmDocumentRelationshipDAO.updateObject(relationshipObj);
  	        }
  	      }
  	      if(indirectRelationDocumentList.size()>0){
  	        for(int n=0;n<indirectRelationDocumentList.size();n++){
  	          MtmDocumentRelationship relationshipObj =(MtmDocumentRelationship)indirectRelationDocumentList.get(n);
  	          relationshipObj.setRecordStatus(GlobalConstant.RECORD_STATUS_INACTIVE);
  	          dmsMtmDocumentRelationshipDAO.updateObject(relationshipObj);
  	        }
  	      }
  	      docOperationManager.deleteDocument(document);
  	    }  
  	  }
	  }catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception e){
      log.error(e.getMessage(), e);
      throw new ApplicationException(e); 
    }
  }
  
  public DmsDocument checkOutDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
    DmsDocument document = null;
    
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    VersionControlManager versionControlManager = new VersionControlManager(sessionContainer, conn);
		    
    try{
     document = docRetrievalManager.getDocument(TextUtility.parseIntegerObj(actionForm.getID()));
        
      versionControlManager.checkoutDocument(DmsVersion.EXCLUSIVE_LOCK, document);
      versionControlManager.release();
    }catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception e){
      log.error(e.getMessage(), e);
      throw new ApplicationException(e);
    }
    return document;
  }
  
  public void checkInDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form; 
	    
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    VersionControlManager versionControlManager = new VersionControlManager(sessionContainer, conn);
	
    InputStream inputStream = null;
    FormFile formFile = null;
    Integer documentID = TextUtility.parseIntegerObj(actionForm.getID());
    try{
      if (DmsOperationConstant.NO_UPDATE_CHECKIN.equals(actionForm.getOpMode())) {
    	String sCurFunctionCode = docRetrievalManager.getCurFunctionCode(docRetrievalManager.getDocument(documentID));
        if (SystemFunctionConstant.DMS_PUBLIC_FOLDER.equals(sCurFunctionCode)){
          versionControlManager.unlockDocumentForNoUpdateCheckin(documentID);    	  
        }
      }else if (DmsOperationConstant.CHECKIN_MINOR.equals(actionForm.getOpMode())) {
    	DmsVersion version = docRetrievalManager.getTopVersionByDocumentID(documentID);

        DmsVersion latestVersion = version;
        DmsVersionDAObject versionDAO = new DmsVersionDAObject(sessionContainer, conn);
        List versionList = versionDAO.getParentVersionsListByParentIDByDocumentID(new Integer(0), documentID); //first level
        if (versionList.size() > 0) {
          latestVersion = (DmsVersion)versionList.get(0);
        }
        if (latestVersion.getParentID().intValue() == 0){
          version.setParentID(latestVersion.getID());
        }else{
          version.setParentID(latestVersion.getParentID());
        }

        //When there is a new update for check-in
        formFile = actionForm.getUploadFile();
        inputStream = formFile.getInputStream();
        version.setItemSize(new Integer(formFile.getFileSize()));
        version.setDocumentID(documentID);
        version.setCheckinFileName(formFile.getFileName());
        version.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        
        DmsVersion newVersion = versionControlManager.checkinDocument(true, DmsOperationConstant.CREATE_MINOR_CHECKIN, documentID, version, inputStream);
        
        versionDAO=null;
      }else if (DmsOperationConstant.CHECKIN_OPERATION.equals(actionForm.getOpMode())) {
    	DmsVersion version = docRetrievalManager.getTopVersionByDocumentID(documentID);

        //DmsVersion latestVersion = version;
        DmsVersionDAObject versionDAO = new DmsVersionDAObject(sessionContainer, conn);
        
        //set default to zero as parent for linear versioning
        version.setParentID(new Integer(0));
        
        formFile = actionForm.getUploadFile();
        String realDocumentName = formFile.getFileName();
        inputStream = formFile.getInputStream();
        version.setItemSize(new Integer(formFile.getFileSize()));
        version.setDocumentID(documentID);
        
        String sCurFunctionCode = docRetrievalManager.getCurFunctionCode(docRetrievalManager.getDocument(documentID));
        
        if (SystemFunctionConstant.DMS_PUBLIC_FOLDER.equals(sCurFunctionCode)) { 
          if (sessionContainer.getAppContainer().isLightVersion() && checkExistingVersion(version,form)){
            deleteOldVersion(version.getDocumentID(),form);
          }
        }
        
        DmsVersion newVersion = versionControlManager.checkinDocumentName(true, DmsOperationConstant.CREATE_NEW_CHECKIN, documentID, version, inputStream, realDocumentName);
        
      }
      versionControlManager.release();
      docRetrievalManager.release();
    }catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception e){
      log.error(e.getMessage(), e);
      throw new ApplicationException(e);
    }
  }
  
  public void copyDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
    DmsDocument copiedDocument = new DmsDocument();
	    
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
	    
    Integer sourceID = TextUtility.parseIntegerObj(actionForm.getID());
    Integer destinationID = TextUtility.parseIntegerObj(actionForm.getDestinationID());
    
    //get the destination file
    DmsDocument destinationDoc = docRetrievalManager.getDocument(destinationID);
    Integer targetRootID = destinationDoc.getRootID();
    try{     
      DmsDocument sourceDocument = docRetrievalManager.getDocument(sourceID);
      sourceDocument.setDocumentName(actionForm.getDocumentName());
       
      if (DmsDocument.FOLDER_TYPE.equals(sourceDocument.getDocumentType()) || DmsDocument.COMPOUND_DOC_TYPE.equals(sourceDocument.getDocumentType()) || DmsDocument.PAPER_DOC_TYPE.equals(sourceDocument.getDocumentType())) {
        copiedDocument = docOperationManager.copyFolder(sourceDocument, destinationDoc, targetRootID, DmsOperationConstant.COPY_OPERATION_AS_NEW, DmsOperationConstant.COPY_ALL_VERSIONS, DmsOperationConstant.NO_STRUCTURE_COPY, true);
      } else {
        copiedDocument = docOperationManager.copyDocument(sourceDocument, destinationDoc, targetRootID, DmsOperationConstant.COPY_OPERATION_AS_NEW, DmsOperationConstant.COPY_ALL_VERSIONS, true); 
      }     
      DmsDocument  newDocument = docRetrievalManager.getRelationshipTargetDocument(sourceID,DmsDocument.DOCUMENT_LINK);
     
    }catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception e){
      log.error(e.getMessage(), e);
      throw new ApplicationException(e);
    }
  }
  
  public void moveDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
    DmsDocument copiedDocument = new DmsDocument();
		    
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
    DocumentValidateManager docValidateManager = new DocumentValidateManager(sessionContainer, conn);	 
    
    try{
      Integer sourceID = TextUtility.parseIntegerObj(actionForm.getID());
      Integer destinationID = TextUtility.parseIntegerObj(actionForm.getDestinationID());
    
      DmsDocument sourceDocument = docRetrievalManager.getDocument(sourceID);
      DmsDocument oldSourceDocument=docRetrievalManager.getDocument(sourceID);
    
      sourceDocument.setDocumentName(actionForm.getDocumentName());
      oldSourceDocument.setDocumentName(actionForm.getDocumentName());
	    
      //get the destination file
      DmsDocument destinationDoc = docRetrievalManager.getDocument(destinationID);
      Integer targetRootID = destinationDoc.getRootID();
    
      docValidateManager.checkHasPermissionOnObject(GlobalConstant.OBJECT_TYPE_DOCUMENT, destinationDoc.getID(), destinationDoc.getRootID(), "I");
    	
      if (DmsDocument.FOLDER_TYPE.equals(sourceDocument.getDocumentType()) || DmsDocument.COMPOUND_DOC_TYPE.equals(sourceDocument.getDocumentType()) || DmsDocument.PAPER_DOC_TYPE.equals(sourceDocument.getDocumentType())) {
        docOperationManager.moveFolder(oldSourceDocument, destinationDoc, targetRootID, true);
      } else {
        docOperationManager.moveDocument(oldSourceDocument, destinationDoc, targetRootID, false, true);
      }
	     
    }catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception e){
      log.error(e.getMessage(), e);
      throw new ApplicationException(e);
    }
  }
  
  public List versionDocument(AbstractActionForm form) throws ApplicationException {
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
    List result = new ArrayList();
    
    DmsVersionDAObject versionDAO = new DmsVersionDAObject(sessionContainer, conn); 
    Integer documentID = TextUtility.parseIntegerObj(actionForm.getID());
    result = versionDAO.getVersionsListByDocumentID(documentID,"DESC");	    
		     
	return result;
  }
  
  public List advSearchDocument(AbstractSearchForm form) throws ApplicationException {
	ListDmsDocumentForm actionForm = (ListDmsDocumentForm) form;
    List result = new ArrayList();
	    
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);   
    String rootID = actionForm.getRootID();
    String parentID = actionForm.getParentID();
    String[] searchFolder = actionForm.getSearchFolder();
    List targetRootIDs = Utility.getList(searchFolder);
    actionForm.setAdvSearchOpt(DmsOperationConstant.ATTR_SEARCH_OPERATION);
    result = docRetrievalManager.searchDocumentBySearchObject(actionForm, targetRootIDs); 
    //DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
    //result = dmsDocumentDAO.getAdvanceSearchList(actionForm, targetRootIDs);
    //dmsDocumentDAO = null;
    return result;
  }
  
  /**
   * Search index reocrd from lucene
   * @param form
   * @return
   * @throws ApplicationException
   */
  public List keywordSearchDocument(AbstractSearchForm form ) throws ApplicationException {
    ListDmsDocumentForm searchForm = (ListDmsDocumentForm) form;
    
    List docList = new ArrayList();

    IndexManager indexManager = null;   
    try {
      indexManager = new IndexManager(sessionContainer, conn);    
      
      BooleanQuery booleanQuery = new BooleanQuery();
      Query query1 = null;
      Query query2 = null;
      Query query3 = null;
      Query query4 = null;

      Analyzer stdAnalyzer = indexManager.getAnalyzer();     

      String keyword = searchForm.getKeyword();
      IndexKeywordParser keywordParser = new IndexKeywordParser(sessionContainer, conn);
      keywordParser.parse(keyword);
      String convertKeyword = keywordParser.getParseKeywordString();
      
      // set search fields
      String defaultIndexSize =SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_DEFAULT_PROFILE_FIELD_COUNT);
      int intDefaultIndexSize = (defaultIndexSize==null ? 0 : Integer.parseInt(defaultIndexSize));
      String userDefinedIndexSize =SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_MAX_INDEX_FIELDS);
      int intUserDefinedIndexSize = (userDefinedIndexSize==null ? 0 : Integer.parseInt(userDefinedIndexSize));
      String[] fields = new String[4+intDefaultIndexSize+intUserDefinedIndexSize];
      fields[0] = FieldNames.DOCUMENT_NAME; fields[1] = FieldNames.REFERENCE_NO;
      fields[2] = FieldNames.DESCRIPTION; fields[3] = FieldNames.CONTENT;
      for (int i=0; i<intDefaultIndexSize; i++) {
        fields[4+i] = FieldNames.DEFAULT_INDEXES+i;
      }
      for (int i=0; i<intUserDefinedIndexSize; i++) {
        fields[4+intDefaultIndexSize+i] = FieldNames.USER_DEFINED_INDEXES+i;
      }
      
      // set occur
      BooleanClause.Occur[] flags = new BooleanClause.Occur[4+intDefaultIndexSize+intUserDefinedIndexSize];
      for (int i=0; i<flags.length; i++) {
        flags[i] = BooleanClause.Occur.SHOULD;
      }

      query1 = MultiFieldQueryParser.parse(convertKeyword, fields, flags, stdAnalyzer);
      booleanQuery.add(query1, BooleanClause.Occur.MUST);
      
      // root limit
      String[] searchFolder = searchForm.getSearchFolder();
      String rootStr = "("+FieldNames.ROOT_ID+":\"0\"";
      if (!Utility.isEmpty(searchFolder)) {
        for (int i = 0; i < searchFolder.length; i++) {
          rootStr += " || "+FieldNames.ROOT_ID+":\"" + searchFolder[i] + "\"";
        }
      }
      rootStr += ")";
      query2 = new QueryParser(FieldNames.ROOT_ID, stdAnalyzer).parse(rootStr);
      booleanQuery.add(query2, BooleanClause.Occur.MUST);
      
      //user define field limit
      String[] searchUDF = searchForm.getSearchUDF();
      String udfStr = "("+FieldNames.USER_DEFINED_INDEX_ID+":\"0\"";
      if (!Utility.isEmpty(searchUDF)) {
        for (int i = 0; i < searchUDF.length; i++) {
          if("-1".equals(searchUDF[i])){
            udfStr += " || "+FieldNames.USER_DEFINED_INDEX_ID+":" + "\\"+searchUDF[i] + "";
          }else{
            udfStr += " || "+FieldNames.USER_DEFINED_INDEX_ID+":\"" + searchUDF[i] + "\"";
          }
        }
      }
      udfStr += ")"; 
      if (!Utility.isEmpty(searchUDF)) {
        query3 =  new QueryParser(FieldNames.USER_DEFINED_INDEX_ID, stdAnalyzer).parse(udfStr);
        booleanQuery.add(query3, BooleanClause.Occur.MUST);
      }
      query4 = new TermQuery(new Term(FieldNames.RECORD_STATUS, GlobalConstant.RECORD_STATUS_ACTIVE));
      booleanQuery.add(query4, BooleanClause.Occur.MUST);
      // if show expire is require need ......
      // if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){

      // set sort object
      Sort sort = new Sort();
      boolean reverse = false;
      String sortAttribute = searchForm.getSortAttribute();
      String sortOrder = searchForm.getSortOrder();
      if((!Utility.isEmpty(sortAttribute)) && ("DESC".equals(sortOrder))) {
        reverse=true;
      }
      if(searchForm.getSortByScore() || Utility.isEmpty(sortAttribute) ||Utility.isEmpty(sortOrder)) {
        searchForm.setSortAttribute("");
        searchForm.setSortOrder("");
        sort.setSort(SortField.FIELD_SCORE);
      } else if("DOCUMENT_NAME".equals(sortAttribute)) {
        sort.setSort(FieldNames.DOCUMENT_NAME_SORT, reverse);
      } else if("ITEM_SIZE".equals(sortAttribute)) {
        sort.setSort(FieldNames.ITEM_SIZE, reverse);
      } else if("ITEM_STATUS".equals(sortAttribute)) {
        sort.setSort(FieldNames.ITEM_STATUS,reverse);
      } else if("UPDATER_ID".equals(sortAttribute)) {
        sort.setSort(FieldNames.UPDATER_ID, reverse);
      } else if("UPDATE_DATE".equals(sortAttribute)) {
        sort.setSort(FieldNames.UPDATE_DATE, reverse);
      } else {
        sort.setSort(SortField.FIELD_SCORE);
      }
      
      // set page information
      Pager pager = new Pager();
      int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
      int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
      int pageIndex = ((startOffset-1)/pageSize +1);
      pager.setPageIndex(pageIndex);
      pager.setPageSize(pageSize);
      

      // begin search lucenes
      List indexDocumentList = indexManager.queryIndexDocuments(booleanQuery, sort, pager);
      
      DmsDocumentDAObject dmsDocumentDAO = new DmsDocumentDAObject(sessionContainer, conn);
      
      for (int i=0; i<indexDocumentList.size(); i++) {
        IndexDocument indexDocument = (IndexDocument)indexDocumentList.get(i);
        DmsDocument dmsDocument= (DmsDocument)dmsDocumentDAO.getObjectByID(new Integer(indexDocument.getUid()));
        if (dmsDocument!=null) {
          dmsDocument.setRowNum((pager.getPageIndex()-1)*pager.getPageSize() + 1 + i);
          dmsDocument.setRecordCount(pager.getRecordCount());
          docList.add(dmsDocument);
        }
      }
      sessionContainer = null;
    }catch(ApplicationException apEx){
      throw apEx;
    } catch (Exception e) {
      log.error("Search error.", e);
    } finally {
      conn = null;
      indexManager.close();
    }
    return docList;
    /*
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);

    ListDmsDocumentForm searchForm = (ListDmsDocumentForm) form;
    List docList = new ArrayList();

    try {
      String[] searchFolder = searchForm.getSearchFolder();

      BooleanQuery bq = new BooleanQuery();
      Query query1 = null;
	  Query query2 = null;
	  Query query3 = null;
	  Query query4 = null;
	  Query query5 = null;
	  Query query6 = null;

	  Hits hits = null;
	  String keyword = null;
	  String maxresults = null;
	  
	  keyword = searchForm.getKeyword();
	  Analyzer stdAnalyzer = new StandardAnalyzer();
	  Analyzer analyzer = new StandardAnalyzer();

	  String rootStr = "(ROOT_ID:\"0\"";
	  if (!Utility.isEmpty(searchFolder)) {
	    for (int i = 0; i < searchFolder.length; i++) {
	      rootStr += " || ROOT_ID:\"" + searchFolder[i] + "\"";
	    }
	  }
	  rootStr += ")";

	  //to search only non folder type document
	  String documentTypeStr="(DOCUMENT_TYPE:  \"" + DmsDocument.DOCUMENT_TYPE+ "\"";
	  documentTypeStr += " || DOCUMENT_TYPE:\"" + DmsDocument.COMPOUND_DOC_TYPE + "\"";
	  documentTypeStr += " || DOCUMENT_TYPE:\"" + DmsDocument.DOCUMENT_LINK + "\"";
	  documentTypeStr += " || DOCUMENT_TYPE:\"" + DmsDocument.PAPER_DOC_TYPE + "\"";
	  documentTypeStr +=")";

	  Timestamp currTime = Utility.getCurrentTimestamp();
	  Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
	  String effectiveStartDateCri = IndexManager.formDateRangeSearchString("EFFECTIVE_START_DATE",null,Utility.stripToMinutes(currTime),true);
	  String effectiveEndDateCri = IndexManager.formDateRangeSearchString("EFFECTIVE_END_DATE",Utility.stripToMinutes(oneDayBeforeCurrTime),null,true);
	  String ownerIDCri = IndexManager.formSearchString(IndexManager.INDEX_NAME_OWNER_ID,sessionContainer.getUserRecordID().toString(),true);
	  String defaultCriteria = "(("+effectiveStartDateCri+" AND "+ effectiveEndDateCri +")" + " OR " + ownerIDCri +")" ;
	  QueryParser qParser = new QueryParser("DEFAULT",analyzer);
	  boolean isRelationWord = SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_RELATIONAL_WORD_ENABLE);
	  DmsRelationalWordDAObject dmsRelationalWordDaobject = new DmsRelationalWordDAObject(sessionContainer, conn);
      String testKeyWord="";
	  String nKeyword="";
	  try {
	    log.debug("keyword include = " + keyword);

	    String sKeyword=TextUtility.convert(keyword);//convert big5 to gb or gb to big5
	    nKeyword= keyword+" || "+sKeyword;
	    if(isRelationWord){//relatioanal word
	      List wordList=this.searchRelationalWord(keyword);
	        if(wordList.size()>1){
	          for(int i=0;i<wordList.size();i++){
	            if(keyword.indexOf("&&")>0){
	              testKeyWord+="&&"+"("+wordList.get(i).toString()+")";
                }else {
                  testKeyWord+="||"+"("+wordList.get(i).toString()+")";
	            }
	            nKeyword=testKeyWord.substring(2,testKeyWord.length());
	          }
	        }else{
	          List relationalWordList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(keyword);
	          for(int i=0;i<relationalWordList.size();i++){
	            DmsRelationalWord dmsRelationalWord = (DmsRelationalWord)relationalWordList.get(i);
	            String relationKeyWord = dmsRelationalWord.getWord();
	            nKeyword = nKeyword+" || " +"\""+TextUtility.convert(relationKeyWord) +"\""+" || " +"\""+relationKeyWord +"\"";
	          }
	        }
	      }

	    String[] fields ={"FULL_TEXT","ALL_RELATED_INDEXES"};
	    query6 = MultiFieldQueryParser.parse(nKeyword, fields, analyzer);
	    query2 = QueryParser.parse(rootStr, "ROOT_ID", stdAnalyzer);
	    query3 = QueryParser.parse(GlobalConstant.RECORD_STATUS_ACTIVE + GlobalConstant.RECORD_STATUS_ACTIVE, IndexManager.INDEX_NAME_RECORD_STATUS, analyzer);
	    query4 = qParser.parse(defaultCriteria);
	    bq.setMaxClauseCount(1000000);
	    bq.add(query2, true, false);
	    bq.add(query3, true, false);
	    bq.add(query6, true, false);

	    if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
	      bq.add(query4, true, false);
	    }
	  } catch (ParseException e) {
	    log.error(e.getMessage(), e);
	    throw new ApplicationException(e);
	  }
	      
	  hits = FullTextIndexFactory.getInstance().queryHits(bq, sessionContainer, searchForm.getSortAttribute(), searchForm.getSortOrder());

	  docList = (List) docRetrievalManager.retrieveDmsDocListFromLuceneDocList(searchForm, hits);
	      
	  sessionContainer = null;
	  docRetrievalManager.release();
	}catch(ApplicationException apEx){
	  throw apEx;
	} catch (Exception e) {
	  log.error(e.getMessage(), e);
	  throw new ApplicationException(e);
	} finally {
	  conn = null;
	}
	return docList;
  */
  }
  
  /**
   * Perform index action, update new index content.
   * @param form
   * @return
   * @throws ApplicationException
   */
  public String indexDocument(AbstractActionForm form) throws ApplicationException {
   // MaintDmsFullTextViewerForm actionForm = (MaintDmsFullTextViewerForm) form;
    MaintDmsWindowsClientForm actionForm = (MaintDmsWindowsClientForm) form;
    
    InputStream fullTextFileInputStream = null;
    FormFile fullTextIndex = null;
    Query query = null;
    Hits hits = null;
    String content = "";
  
    try{  	
      String opMode = actionForm.getOpMode();    
      Integer documentID = TextUtility.parseIntegerObj(actionForm.getID()); 
      DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer,conn); 
      DmsDocument dmsDocument = docRetrievalManager.getDocument(documentID);
      /*
      String[] feild ={FieldNames.CONTENT};     
  
      Analyzer analyzer = new org.apache.lucene.analysis.WhitespaceAnalyzer();
      QueryParser qParser = new QueryParser("CON", analyzer);
      query = qParser.parse();
    
      hits = FullTextIndexFactory.getInstance().queryHits(query, sessionContainer,null,null); 
      //actionForm.setHistLength(hits.length());      
      if(hits.length() > 0){
        Document doc = hits.doc(0);      
        content = TextUtility.noNull(doc.get("FULL_TEXT"));
      }      
      */
      if (GlobalConstant.OP_MODE_UPDATE.equals(opMode)){ 
        content = actionForm.getContent();
        if(!Utility.isEmpty(content)){
          fullTextFileInputStream= new java.io.ByteArrayInputStream(content.getBytes("UTF-8"));
          this.updateFullTextViewer(dmsDocument,fullTextFileInputStream, null);
        }
      }         
    } catch (ApplicationException apEx){
      throw apEx;
    }catch (Exception ioe) {
      log.error(ioe.getMessage(), ioe);
      throw new ApplicationException(ErrorConstant.DMS_CONTENT_VIEWER_UPDATE_ERROR, ioe);
    } 
    return content;
  }  
  
  
  
  /**
   * Delete the oldest Version (ver no.1) and shift the version status on the
   * updatedVersion (ver no.2)
   * 
   * @param documentID
   * @param request
   * @param form
   * @throws ApplicationException
   */
  public void deleteOldVersion(Integer documentID, AbstractActionForm form) throws ApplicationException {

    MaintDmsVersionForm versionForm = (MaintDmsVersionForm) form;
    documentID = TextUtility.parseIntegerObj(versionForm.getID());
    DmsContentDAObject dmsContentDAO = new DmsContentDAObject(sessionContainer, conn);
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
    DmsDocument dmsDocument = docRetrievalManager.getDocument(documentID);
    DmsVersionDAObject dmsVersionDAOject = new DmsVersionDAObject(sessionContainer, conn);
    MtmDocumentVersionDAObject mtmDocumentVersionDAOject = new MtmDocumentVersionDAObject(sessionContainer,
        conn);
    List list = dmsVersionDAOject.getVersionsListByDocumentID(documentID, "desc");
    DmsVersion oldVersion = new DmsVersion();
    DmsDocumentNameConvertor documentNameConvertor = null;
    DmsVersion ver = new DmsVersion();
    DmsContentManager dmsContentManager = new DmsContentManager(sessionContainer, conn);

    // Update the version information
    String conName = "";
    if (list.size() >= 2) {
      ver = (DmsVersion) list.get(0);
      ver.setVersionLabel("ROOT");
      ver.setVersionNumber("1");
      DmsVersion version = (DmsVersion) dmsVersionDAOject.updateObject(ver);
      list.remove(ver);

      for (int i = 0; i < list.size(); i++) {
        oldVersion = (DmsVersion) list.get(i);
        // Hard Delete the record in MTM_DOCUMENT_VERSION
        mtmDocumentVersionDAOject.deleteObjectByID(oldVersion.getID());

        // Hard Delete the physical file
        if (!DmsDocument.FOLDER_TYPE.equals(dmsDocument.getDocumentType())) {
          DmsContent tmpContent = docRetrievalManager.getContentByContentID(oldVersion.getContentID());
          dmsContentManager.deleteDmsDocumentStoreContent(dmsDocument, tmpContent);

          // Hard Delete the DmsContent record in DMS_CONTENT
          dmsContentDAO.hardDeleteByID(tmpContent.getID());
          // Hard Delete the DmsVersion record in DMS_VERSION
          dmsVersionDAOject.hardDeleteByID(oldVersion);
        }
      }
      try {
        documentNameConvertor = (DmsDocumentNameConvertor) Class.forName(
            SystemParameterFactory.getSystemParameter(SystemParameterConstant.DMS_NAME_CONVERTOR_CLASS))
            .newInstance();
      } catch (Exception e) {
        log.error("Name Convertor class not found.", e);
        throw new ApplicationException(DmsErrorConstant.NAME_CONVERTOR_CLASS_NOT_FOUND, e);
      }
      docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
      dmsContentDAO = new DmsContentDAObject(sessionContainer, conn);

      // for (int i=0; i<list.size(); i++){
      DmsDocument document = docRetrievalManager.getDocument(ver.getDocumentID());
      DmsContent dmsContent = (DmsContent) dmsContentDAO.getObjectByID(ver.getContentID());
      if (ver != null) {
        document.setVersionNumber(ver.getVersionNumber());
        log.debug("version number = " + ver.getVersionNumber());
        String newConvertedName = documentNameConvertor.encryptDocumentName(document);
        log.debug("content number = " + ver.getContentID());
        if (ver.getContentID() != null && ver.getContentID().intValue() > 0) {
          DmsContent content = (DmsContent) dmsContentDAO.getObjectByID(ver.getContentID());
          // Update physical filename in storage location
          String oldConvertedName = content.getConvertedName();
          // if (!DmsDocument.FOLDER_TYPE.equals(document.getDocumentType())){
          String foldersDir = docRetrievalManager.getFoldersDirectories(document).toString();
          log.debug("parent FolderPath = " + foldersDir);
          File oldDocumentFile = new File(foldersDir + oldConvertedName);
          File newDocumentFile = new File(foldersDir + newConvertedName);
          log.debug("oldDocumentFile  = " + oldDocumentFile.getAbsolutePath());
          log.debug("newDocumentFile  = " + newDocumentFile.getAbsolutePath());
          if (oldDocumentFile.isFile()) {
            log.debug("oldDocumentFile  exists");
            if (!oldDocumentFile.renameTo(newDocumentFile)) {
              log.error("Rename file operation fail.");
              throw new ApplicationException(DmsErrorConstant.RENAME_FILE_ERROR);
            }
            if (oldDocumentFile.exists()) {
              oldDocumentFile.delete();
            }
          }
          // }

          // Update DMS_CONTENT table; change the converted name
          content.setConvertedName(newConvertedName);
          dmsContentDAO.updateObject(content);

        }
      }
      //}
    }
  }
 
 /**
  * Check does the new updated version pass the limitation on Light Version
  * @param newVersion
  * @param request
  * @param form
  * @return
  * @throws ApplicationException
 */
 public boolean checkExistingVersion(DmsVersion newVersion,AbstractActionForm form) throws ApplicationException{
   MaintDmsVersionForm versionForm = (MaintDmsVersionForm)form;
   Integer documentID = TextUtility.parseIntegerObj(versionForm.getID());  	
   DmsVersionDAObject dmsVersionDAOject = new DmsVersionDAObject(sessionContainer,conn);
   List list = dmsVersionDAOject.getVersionsListByDocumentID(documentID,"desc"); 
   if(list.size()>1){
     return true;
   }   
   return true;
 }
 
 public String getUserNameByID(Integer ID) throws ApplicationException{
   String loginName = "";
   
   UserRecordDAObject userRecordDAObject = new UserRecordDAObject(sessionContainer,conn);
   UserRecord userRecord = (UserRecord)userRecordDAObject.getObjectByID(ID);
   if(!Utility.isEmpty(userRecord)){
     loginName = userRecord.getLoginName();
   }   
   return loginName;
 }
 
   public List searchRelationalWord(String keyword) throws ApplicationException {
     List relationList = new ArrayList();
     List relationTestList = new ArrayList();
     String nKeyword="";
     String word="";
     try{
       DmsRelationalWordDAObject dmsRelationalWordDaobject = new DmsRelationalWordDAObject(sessionContainer, conn);
       if(keyword.startsWith("\"")){
          if(keyword.indexOf("||")>0){
            String []keyWord=TextUtility.splitString(keyword,"||");

            for(int i=0;i<keyWord.length;i++){
              if(!keyWord[i].equals("||")){
                word=keyWord[i];
                String testWord=word.substring(word.indexOf("\"")+1,word.lastIndexOf("\""));
                 List relationalWordList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(testWord);
                 for(int n=0;n<relationalWordList.size();n++){
                   DmsRelationalWord dmsRelationalWord = (DmsRelationalWord)relationalWordList.get(n);
                   String relationKeyWord = dmsRelationalWord.getWord();
                   testWord = testWord+" || " +"\""+TextUtility.convert(relationKeyWord) +"\""+" || " +"\""+relationKeyWord +"\"";
                 }
                 relationList.add(testWord);
               }
            }
          }else if(keyword.indexOf("&&")>0){
            String []keyWord=TextUtility.splitString(keyword,"&&");
            for(int i=0;i<keyWord.length;i++){
               if(!keyWord[i].equals("&&")){
                 word=keyWord[i];
                 String testWord=word.substring(word.indexOf("\"")+1,word.lastIndexOf("\""));
                 List relationalWordList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(testWord);
                 for(int n=0;n<relationalWordList.size();n++){
                   DmsRelationalWord dmsRelationalWord = (DmsRelationalWord)relationalWordList.get(n);
                   String relationKeyWord = dmsRelationalWord.getWord();
                   testWord = testWord+" || " +"\""+TextUtility.convert(relationKeyWord) +"\""+" || " +"\""+relationKeyWord +"\"";
                 }
                 relationList.add(testWord);
                }

            }
          }
        }else{
          if(keyword.indexOf("&&")>0){
            String []keyWord=TextUtility.splitString(keyword,"&&");
            String test="";
            String keyWord1="";
            for(int i=0;i<keyWord.length;i++){
                word=keyWord[i];
                String []testWord=TextUtility.splitString(word," ");
                for(int d=0;d<testWord.length;d++){
                  keyWord1=testWord[d];
                  List relationalWordList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(testWord[d]);
                  for(int n=0;n<relationalWordList.size();n++){
                    DmsRelationalWord dmsRelationalWord = (DmsRelationalWord)relationalWordList.get(n);
                    String relationKeyWord = dmsRelationalWord.getWord();
                    keyWord1 = keyWord1+" || "+"\""+TextUtility.convert(relationKeyWord) +"\""+" || " +"\""+relationKeyWord +"\"";
                  }
                  test=test+"||"+"("+keyWord1+")";
                }
                String []test1=TextUtility.splitString(test.substring(2),"||()||");
                String test2="";
                for(int x=0;x<test1.length;x++){
                   test2=test1[x];
                }
                relationList.add(test2);
            }
          }else if(keyword.indexOf("||")>0){
             String []keyWord=TextUtility.splitString(keyword," ");
             for(int i=0;i<keyWord.length;i++){
               if(!keyWord[i].equals("||")){
                 word=keyWord[i];
                 List relationalWordList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(keyWord[i]);
                 for(int n=0;n<relationalWordList.size();n++){
                   DmsRelationalWord dmsRelationalWord = (DmsRelationalWord)relationalWordList.get(n);
                   String relationKeyWord = dmsRelationalWord.getWord();
                   word = word+" || " +"\""+TextUtility.convert(relationKeyWord) +"\""+" || " +"\""+relationKeyWord +"\"";
                 }
                relationList.add(word);
               }
             }
          }else{
             String []keyWord=TextUtility.splitString(keyword," ");
             for(int i=0;i<keyWord.length;i++){
                word=keyWord[i];
                List relationalWordList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(keyWord[i]);
                for(int n=0;n<relationalWordList.size();n++){
                  DmsRelationalWord dmsRelationalWord = (DmsRelationalWord)relationalWordList.get(n);
                  String relationKeyWord = dmsRelationalWord.getWord();
                  word = word+" || " +"\""+TextUtility.convert(relationKeyWord) +"\""+" || " +"\""+relationKeyWord +"\"";
                }
                relationList.add(word);
             }
          }
       }
     }catch (ApplicationException apEx){
       throw apEx;
     }catch (Exception e) {
       log.error(e.getMessage(), e);
       throw new ApplicationException(e);
     }finally {
        conn = null;
     }
    return relationList;
  }
   
   public void updateFullTextViewer(DmsDocument dmsDocument,InputStream data,String extention)throws ApplicationException{
     IndexManager idxHandler = new IndexManager(this.sessionContainer, this.conn);
     idxHandler.updateDmsDocument(dmsDocument, data, extention);
   }
}
